
/**
 * @file main
 *
 */

/*********************
 *      INCLUDES
 *********************/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

#include "lvgl.h"
#include "lv_conf.h"
#include "lv_drv_conf.h"
#include "lv_demo_conf.h"

#include "lv_demos/lv_demo.h"
// #include "apps/rtsp/rtsp.h"
// #include "apps/rtsp/ffmpeg_rtsp.h"
// #include "apps/demo/demo.h"
// #include "apps/benchmark/benchmark.h"
// #include "lv_examples/lv_apps/sysmon/sysmon.h"
// #include "lv_examples/lv_apps/terminal/terminal.h"
// #include "lv_examples/lv_apps/tpcal/tpcal.h"
// #include "lv_examples/lv_tests/lv_test.h"

#if USE_WINDOWS
#include "lv_drivers/win_drv.h"
#include <windows.h>
#else
#include "lv_drivers/sdl/sdl.h"
#include <SDL2/SDL.h>
#endif // USE_WINDOWS

/*********************
 *      DEFINES
 *********************/

/**********************
 *      TYPEDEFS
 **********************/

/**********************
 *  STATIC PROTOTYPES
 **********************/
static void hal_init(void);

/**********************
 *  STATIC VARIABLES
 **********************/

/**********************
 *      MACROS
 **********************/

/**********************
 *   GLOBAL FUNCTIONS
 **********************/
#if USE_LV_EXAMPLE
void lv_example_keyboard_1(void);
void lv_example_calendar_1(void);
#endif

#if USE_WINDOWS
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int nCmdShow)
#else
#undef main
int main(int argc, char** argv)
#endif // USE_WINDOWS
{
#if USE_LV_RTSP
    if(argc < 2){
        printf("Please Input rstp url!\n");
        return 0;
    }
    if(argc == 3){
        out_filename = argv[2];
    }
#endif
    /*Initialize LittlevGL*/
    lv_init();
    /*Initialize the HAL for LittlevGL*/
    hal_init();

#if LV_USE_DEMO_WIDGETS
    lv_demo_widgets();
#endif

#if LV_USE_DEMO_BENCHMARK
    lv_demo_benchmark();
#endif

#if LV_USE_DEMO_STRESS
    lv_demo_stress();
#endif

#if LV_USE_DEMO_MUSIC
    lv_demo_music();
#endif

#if USE_LV_EXAMPLE
    lv_example_keyboard_1();
    lv_example_calendar_1();
#endif

#if USE_LV_RTSP
    ffmpeg_init(argv[1]);

    // Load rtsp app
    rtsp_create();
#endif

    /*Load a demo*/
#if USE_LV_DEMO
    demo_create();
#endif
    /*Try the benchmark to see how fast is your GUI*/
#if USE_LV_BENCHMARK
    benchmark_create();
#endif
#if USE_LV_SYSMON
    sysmon_create();
#endif
#if USE_LV_TERMINAL
    terminal_create();
#endif
#if USE_LV_TPCAL
    tpcal_create();
#endif

    /*Check the themes too*/
#if USE_LV_TESTS
    lv_test_theme_1(lv_theme_zen_init(110, NULL));
    lv_test_theme_2();
    /*Test*/
    lv_test_object_1();
    lv_test_stress_1();
    
    /*lv_test_group_1*/
    lv_test_group_1();
#endif
    
    /* Tutorial */
#if USE_LV_TUTORIALS
    lv_tutorial_responsive();
#endif

#if USE_WINDOWS
    while(!lv_win_exit_flag) {
#else
    while(1) {
#endif // USE_WINDOWS
        /* Periodically call the lv_task handler.
         * It could be done in a timer interrupt or an OS task too.*/
        // SDL_LockMutex(lvgl_mutex);
        lv_task_handler();
        // SDL_UnlockMutex(lvgl_mutex);
        SDL_Delay(1);       /*Just to let the system breath*/
    }
    return 0;
}

/**********************
 *   STATIC FUNCTIONS
 **********************/

/**
 * A task to measure the elapsed time for LittlevGL
 * @param data unused
 * @return never return
 */
#if !USE_WINDOWS
#if LV_TICK_CUSTOM == 1
static int tick_thread(void *data)
{
    while(1) {
        lv_tick_inc(1);
        SDL_Delay(1);   /*Sleep for 1 millisecond*/
    }

    return 0;
}
#endif
#endif // USE_WINDOWS

static lv_color_t buf1_1[SDL_HOR_RES * 100];                      /*A buffer for 10 rows*/
static lv_color_t buf1_2[SDL_HOR_RES * 100];                      /*A buffer for 10 rows*/
/**
 * Initialize the Hardware Abstraction Layer (HAL) for the Littlev graphics library
 */
static void hal_init(void)
{
    lv_disp_t *disp;
    static lv_disp_draw_buf_t disp_draw_buf_1;

    lv_disp_draw_buf_init(&disp_draw_buf_1, buf1_1, buf1_2, SDL_HOR_RES * 100);   /*Initialize the display buffer*/

#if !USE_WINDOWS
    /* Add a display */
#if USE_SDL
    sdl_init();

    static lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);            /*Basic initialization*/
    /*Set the resolution of the display*/
    disp_drv.hor_res = SDL_HOR_RES;
    disp_drv.ver_res = SDL_VER_RES;

    // disp_drv.full_refresh = 1;

    /*Used to copy the buffer's content to the display*/
    disp_drv.flush_cb = sdl_display_flush;

    /*Set a display buffer*/
    disp_drv.draw_buf = &disp_draw_buf_1;

    disp = lv_disp_drv_register(&disp_drv);
    if (disp == NULL) {
        printf("disp drv register fail\n");
    }
    lv_theme_t *theme = lv_theme_default_init(disp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), LV_THEME_DEFAULT_DARK, LV_FONT_DEFAULT);
    lv_disp_set_theme(disp, theme);

    lv_group_t *group = lv_group_create();
    lv_group_set_default(group);
#endif

    /* Add the mouse (or touchpad) as input device */
#if USE_SDL
    static lv_indev_drv_t indev_drv_mouse;
    lv_indev_drv_init(&indev_drv_mouse);          /*Basic initialization*/
    indev_drv_mouse.type = LV_INDEV_TYPE_POINTER;
    indev_drv_mouse.read_cb = sdl_mouse_read;         /*This function will be called periodically (by the library) to get the mouse position and state*/
    lv_indev_t *mouse_indev = lv_indev_drv_register(&indev_drv_mouse);

    static lv_indev_drv_t indev_drv_kb;
    lv_indev_drv_init(&indev_drv_kb); /*Basic initialization*/
    indev_drv_kb.type = LV_INDEV_TYPE_KEYPAD;
    indev_drv_kb.read_cb = sdl_keyboard_read;
    lv_indev_t *kb_indev = lv_indev_drv_register(&indev_drv_kb);
    lv_indev_set_group(kb_indev, group);

    static lv_indev_drv_t indev_drv_mw;
    lv_indev_drv_init(&indev_drv_mw); /*Basic initialization*/
    indev_drv_mw.type = LV_INDEV_TYPE_ENCODER;
    indev_drv_mw.read_cb = sdl_mousewheel_read;

    lv_indev_t *mw_indev = lv_indev_drv_register(&indev_drv_mw);
    lv_indev_set_group(mw_indev, group);

    /*Set a cursor for the mouse*/
    LV_IMG_DECLARE(mouse_cursor_icon); /*Declare the image file.*/
    lv_obj_t * cursor_obj = lv_img_create(lv_scr_act()); /*Create an image object for the cursor */
    lv_img_set_src(cursor_obj, &mouse_cursor_icon);           /*Set the image source*/
    lv_indev_set_cursor(mouse_indev, cursor_obj);             /*Connect the image  object to the driver*/

#endif

    /* Tick init.
     * You have to call 'lv_tick_handler()' in every milliseconds
     * Create an SDL thread to do this*/
#if LV_TICK_CUSTOM == 1
    SDL_CreateThread(tick_thread, "tick", NULL);
#endif

#else
    /* This sets up some timers to handle everything. */
    windrv_init();
#endif // USE_WINDOWS
}
